package service

import (
	"encoding/json"
	"fmt"
	"reflect"
	"strings"
)

type StructField struct {
	TenantId string        `sql:"type:bigint(20)" json:"tenant_id"`
	UserId   string        `sql:"type:bigint(20)" json:"user_id"`
	OrderId  string        `sql:"type:bigint(20)" json:"Comment_id"`
	Content  string        `sql:"type:varchar(500)" json:"content"`
	Subject  string        `sql:"type:varchar(50)" json:"subject"`
	Items    []StructField `json:"items"`
}

func main() {

	m := make(map[string]interface{}, 0)
	m["$schema"] = "http://json-schema.org/draft-04/schema#"
	m["type"] = "object"
	edges := EmployeeInsuredPromptResponse{}
	edges = EmployeeInsuredPromptResponse{
		NoChangeEmployee: []*NoChangeEmployee{
			{
				Name: "123",
				//Last1: []*Last1{
				//	{Name: "sad"},
				//},
			},
		},
	}
	//boby := CreateBoby(&edges)
	//fmt.Println(boby)
	nestedStruct := CheckNestedStruct(&edges)
	m["properties"] = nestedStruct
}

type Edge struct {
	Uid  int64   `json:"uid"`
	Name string  `json:"name"`
	Read Article `json:"visited"`
	//ArrayRead []*Article `json:"array_visited"`
}
type Article struct {
	Uid  string  `json:"uid2"`
	Name string  `json:"name2"`
	From []*Site `json:"from,omitempty"`
}
type Site struct {
	Uid  int64  `json:"uid,omitempty"`
	Name string `json:"name,omitempty"`
	Last Last   `json:"Last,omitempty"`
}

type Last struct {
	Uid  string `json:"uid,omitempty"`
	Name string `json:"name,omitempty"`
}

func CreateBoby(edges interface{}) string {
	m := make(map[string]interface{}, 0)
	m["$schema"] = "http://json-schema.org/draft-04/schema#"
	m["type"] = "object"
	nestedStruct := CheckNestedStruct(edges)
	m["properties"] = nestedStruct
	v, _ := json.Marshal(m)
	fmt.Println("打印map:", string(v))
	return string(v)
}
func CheckNestedStruct(edges interface{}) map[string]interface{} {
	m2 := make(map[string]interface{})

	rv := reflect.ValueOf(edges).Elem()
	rt := reflect.TypeOf(edges).Elem()

	for i := 0; i < rt.NumField(); i++ {
		m3 := make(map[string]interface{})
		// 获取json转义
		field := rt.Field(i)
		println("json", field.Tag.Get("json"))
		// 获取类型
		println("Type", field.Type.Kind().String())

		fieldType := field.Type.Kind()
		propertiesType := "string"
		//创建字段类型
		switch fieldType {
		case reflect.String:
			propertiesType = "string"
		case reflect.Struct:
			propertiesType = "object"
		case reflect.Int64, reflect.Int, reflect.Float32, reflect.Float64:
			propertiesType = "number"
		case reflect.Slice:
			propertiesType = "array"
		case reflect.Bool:
			propertiesType = "bool"
		case reflect.Ptr:
			println(field.Type.Elem().Kind().String())
			if field.Type.Kind() == reflect.Ptr {
				switch field.Type.Elem().Kind() {
				case reflect.String:
					propertiesType = "string"
				case reflect.Struct:
					propertiesType = "object"
				case reflect.Int64, reflect.Int, reflect.Float32, reflect.Float64:
					propertiesType = "number"
				case reflect.Slice:
					propertiesType = "array"
				case reflect.Bool:
					propertiesType = "bool"
				}
			}

		}

		if strings.Contains(field.Type.String(), "int") {
			propertiesType = "number"
		}
		fmt.Println("json_type", propertiesType)
		// 普通类型 直接放到map里面
		m3["type"] = propertiesType
		m2[field.Tag.Get("json")] = m3

		// 如果是结构体嵌套解析
		if fieldType == reflect.Struct {
			rm := CheckNestedStruct(rv.Field(i).Addr().Interface())
			m3["properties"] = rm
		}
		// 如果是指针结构体结构体嵌套解析
		if field.Type.Kind() == reflect.Ptr && field.Type.Elem().Kind() == reflect.Struct {
			rm := CheckNestedStruct(rv.Field(i).Interface())
			m3["properties"] = rm
		}

		// 如果是切片    切片长度为零的话会解析失败的
		if fieldType == reflect.Slice {
			fieldSlice := rv.Field(i)
			//获取结构体名称
			println("Type", fieldSlice.Type().Name())
			// 获取结构体类型
			fieldSliceType := fieldSlice.Kind()
			// 嵌套数组
			if fieldSliceType == reflect.Slice {
				i2 := fieldSlice.Addr().Interface()
				//println(reflect.ValueOf(i2).Elem().Kind().String())
				getValue := reflect.ValueOf(i2).Elem()
				if getValue.Kind() != reflect.Slice {
					panic("need slice kind")
				}
				l := getValue.Len()
				// 初始化的时候只创建一个，就循环一次
				for i := 0; i < l; i++ {
					value := getValue.Index(i) // Value of item
					typel := value.Type().Elem()
					//typel.Elem().Kind()
					//println("切片类型：" + typel.Elem().Kind().String())
					// Type of item
					if typel.Kind() != reflect.Struct {
						panic("need struct kind")
					}
					m4 := make(map[string]interface{})
					nestedStruct := CheckNestedStruct(value.Elem().Addr().Interface())

					m4["properties"] = nestedStruct
					// 一般 array 下面就是 结构体
					m4["type"] = "object"
					m3["items"] = m4
					//m3[field.Tag.Get("json")] = m4
					fmt.Printf("type-kind: %s, type-name: %s, value: %v\n", typel.Kind(), typel.Name(), value.Interface())
					// 获取每一个值得信息
					//num := typel.NumField()
					//for j := 0; j < num; j++ {
					//	v := typel.Field(j)
					//
					//	fmt.Printf("name: %s, type: %s, value: %v\n", typel.Field(j).Name, typel.Field(j).Type.String(), typel.Field(j))
					//	if v.Type.Kind() == reflect.Struct {
					//		CheckNestedStruct(m, &v)
					//	}
					//}
				}
			}
		}
	}
	//v, _ := json.Marshal(m2)
	//fmt.Println("打印map:", string(v))
	return m2
}

type EmployeeInsuredPromptResponse struct {
	TotalCount       int64               `protobuf:"bytes,1,rep,name=res" json:"total_count" xml:"res" form:"res"`
	NoChangeEmployee []*NoChangeEmployee `protobuf:"bytes,2,rep,name=no_change_employee,json=noChangeEmployee" json:"no_change_employee" xml:"no_change_employee" form:"no_change_employee"`
}
type NoChangeEmployee struct {
	Customer string `protobuf:"bytes,1,opt,name=customer" json:"customer" xml:"customer" form:"customer"`
	Name     string `protobuf:"bytes,2,opt,name=name" json:"name" xml:"name" form:"name"`
	IdNum    string `protobuf:"bytes,3,opt,name=id_num,json=idNum" json:"id_num" xml:"id_num" form:"id_num"`
	//Last1    []*Last1 `json:"Last1"`
}

type Last1 struct {
	Uid  string `json:"uid,omitempty"`
	Name string `json:"name,omitempty"`
}
type CreateResponse struct {
	Name  string `protobuf:"bytes,2,opt,name=name" json:"name" xml:"name" form:"name"`
	IdNum string `protobuf:"bytes,3,opt,name=id_num,json=idNum" json:"id_num" xml:"id_num" form:"id_num"`
	Item  *Org   `protobuf:"bytes,1,opt,name=item" json:"item" xml:"item"`
}
type Org struct {
	Id          string `protobuf:"bytes,1,opt,name=id" json:"id" xml:"id"`
	Name        string `protobuf:"bytes,2,opt,name=name" json:"name" xml:"name"`
	ParentOrgId string `protobuf:"bytes,3,opt,name=parent_org_id,json=parentOrgId" json:"parent_org_id" xml:"parent_org_id"`
	ParentOrg   string `protobuf:"bytes,4,opt,name=parent_org,json=parentOrg" json:"parent_org" xml:"parent_org"`
	TenantId    string `protobuf:"bytes,5,opt,name=tenant_id,json=tenantId" json:"tenant_id" xml:"tenant_id"`
	OwnerId     string `protobuf:"bytes,6,opt,name=owner_id,json=ownerId" json:"owner_id" xml:"owner_id"`
	Owner       string `protobuf:"bytes,7,opt,name=owner" json:"owner" xml:"owner"`
	CreatedAt   int64  `protobuf:"varint,8,opt,name=created_at,json=createdAt" json:"created_at" xml:"created_at"`
	UpdatedAt   int64  `protobuf:"varint,9,opt,name=updated_at,json=updatedAt" json:"updated_at" xml:"updated_at"`
	OrgCode     string `protobuf:"bytes,10,opt,name=org_code,json=orgCode" json:"org_code" xml:"org_code"`
}
